/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package modele;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontFormatException;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.Vector;
import java.util.List;
import javax.imageio.ImageIO;
import main.Outils;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;

/**
 * Classe d'administration
 * Description : Récupère le contenu des dossiers d'administration
 * et des fichiers de configuration.
 * @author romain
 */
public class Chargeur {

    // Garde-fou
    private static final int NB_COULEUR_MAX = 400;
    private static final int NB_MODELE_MAX = 50;
    private static final int NB_IMAGE_MAX = 40;
    private static final int NB_POLICE_MAX = 200;


    private static final String CHEMIN_COULEURS = "src/config/couleurs.xml";
    private static final String CHEMIN_MODELES = "src/config/modeles.xml";
    private static final String DOSSIER_POLICES = "src/config/polices";
    private static final String DOSSIER_IMAGES = "src/config/images";
    private static final Vector<String> EXTENSIONS_IMAGE_AUTORISEES = new Vector<String>(
            Arrays.asList("jpg", "jpeg"));
    private static final Vector<String> EXTENSIONS_POLICE_AUTORISEES = new Vector<String>(
            Arrays.asList("ttf"));


    /**
     * Liste des éléments du fichier de configuration modèle.
     */
    private final class ConstXmlModeleElements{
        private static final String ELEMENT_ORIENTATION = "orientation";
        private static final String ELEMENT_X = "x";
        private static final String ELEMENT_Y = "y";
        private static final String ELEMENT_LONGEUR = "w";
        private static final String ELEMENT_HAUTEUR = "h";
        private static final String ELEMENT_CARACTERESMAX = "caracteresMax";
        private static final String ELEMENT_TAILLEFONT = "tailleFont";
        private static final String ELEMENT_TEXTE = "texte";
        private static final String ELEMENT_IMAGES = "images";
        private static final String ELEMENT_IMAGE = "image";
        private static final String ELEMENT_ROTATION = "rotation";
        private static final String ELEMENT_PAYSAGE = "paysage";
        private static final String ELEMENT_PORTRAIT = "portrait";
    }

    /**
     * Liste des éléments du fichier de configuration couleur.
     */
    private final class ConstXmlCouleurElements{
        public static final String ELEMENT_R = "r";
        public static final String ELEMENT_V = "v";
        public static final String ELEMENT_B = "b";
    }    

    /**
     * Récupère les images situés dans le chemin défini dans la constante DOSSIER_IMAGES
     * @return Liste des images
     * @throws Exception
     */
    public static Vector<Image> recupereImages() throws Exception {
        File dossierImages = new File(DOSSIER_IMAGES);
        File[] fichiers = null;
        if(dossierImages.isDirectory() && dossierImages.exists()){
            fichiers = dossierImages.listFiles();
        }

        return recupereImages(fichiers);
    }

    /**
     * Récupère l'ensemble des images du dossier spécifié en paramêtre
     * @param Liste des fichiers
     * @return Liste des images
     * @throws IOException
     */
    public static Vector<Image> recupereImages(File[] fichiers) throws IOException{
        Vector<Image> images = new Vector<Image>();

        for (int i = 0; i < fichiers.length && i <= NB_IMAGE_MAX; i++) {
            File fichier = fichiers[i];

            if(EXTENSIONS_IMAGE_AUTORISEES.contains(Outils.recupereExtensionFichier(fichier.getName())))
            {
                Image image =  new Image(fichier.getPath(), null, null, ImageIO.read(fichier));
                images.add(image);

                // Mise en mémoire pour gain de mémoire
                image.creerMiniature( new Dimension(402, 300) );
                image.enregistrerEnMemoire();
            }
        }
        return images;
    }

    /**
     * Récupère les polices situés dans le chemin défini dans la constante DOSSIER_POLICES
     * @return Liste des polices
     * @throws IOException
     * @throws FontFormatException
     */
    public static Vector<Font> recuperePolices() throws IOException, FontFormatException{
        Vector<Font> polices = new Vector<Font>();

        File dossierImages = new File(DOSSIER_POLICES);
        File[] fichiers = null;
        if(dossierImages.isDirectory() && dossierImages.exists()){
            fichiers = dossierImages.listFiles();

            for (int i = 0; i < fichiers.length && i <= NB_POLICE_MAX; i++) {
                File fichier = fichiers[i];

                if(EXTENSIONS_POLICE_AUTORISEES.contains(Outils.recupereExtensionFichier(fichier.getName())))
                {
                    Font police = Font.createFont(Font.TRUETYPE_FONT, fichier);
                    polices.add(police);
                }
            }
        }

        return  polices;
    }

    /**
     * Récupère l'ensemble des couleurs dans le fichiers xml couleurs
     * @return Liste de couleurs
     * @throws JDOMException
     * @throws IOException
     */
    public static Vector<Color> recupereCouleurs() throws JDOMException, IOException{
        SAXBuilder constructeur = new SAXBuilder();
        Vector<Color> couleurs = new Vector<Color>();

        Document policeXml = constructeur.build(CHEMIN_COULEURS);

        if (policeXml.hasRootElement()) {
            Element racine = policeXml.getRootElement();
            List<Element> elements = racine.getChildren();

            //S'il éxiste des couleurs dans le fichier.
            if(elements.size() > 0){
                Element couleurR = null;
                Element couleurV = null;
                Element couleurB = null;

                //Pour chaque élément du fichier
                int i = 0;
                for(Element color : elements){
                    couleurR = color.getChild(ConstXmlCouleurElements.ELEMENT_R);
                    couleurV = color.getChild(ConstXmlCouleurElements.ELEMENT_V);
                    couleurB = color.getChild(ConstXmlCouleurElements.ELEMENT_B);
                    couleurs.add(new Color(
                            Integer.parseInt(couleurR.getText()),
                            Integer.parseInt(couleurV.getText()),
                            Integer.parseInt(couleurB.getText())
                            ));

                    if( ++i >= NB_COULEUR_MAX )
                        return couleurs;
                }
            }
        }

        return couleurs;
    }

    /**
     * Récupère l'ensemble des modèles dans le fichier xml modèle
     * @return Liste des modèles
     * @throws JDOMException
     * @throws IOException
     */
    public static Vector<ModeleCarte> recupereModeles() throws JDOMException, IOException{
        SAXBuilder constructeur = new SAXBuilder();
        Vector<ModeleCarte> modeles = new Vector<ModeleCarte>();

        Document policeXml = constructeur.build(CHEMIN_MODELES);

        if (policeXml.hasRootElement()) {
            Element racine = policeXml.getRootElement();
            List<Element> xmlModeles = racine.getChildren();

            int i = 0;
            for(Element xmlModele : xmlModeles){
                ModeleCarte.Orientation orientation;
                orientation = (xmlModele.getChildText(ConstXmlModeleElements.ELEMENT_ORIENTATION).equals(ConstXmlModeleElements.ELEMENT_PAYSAGE))
                        ? ModeleCarte.Orientation.PAYSAGE
                        : ModeleCarte.Orientation.PORTRAIT;

                Element xmlTextElement = xmlModele.getChild(ConstXmlModeleElements.ELEMENT_TEXTE);
                ZoneTexte zoneDeTexte = new ZoneTexte(
                        Integer.parseInt(xmlTextElement.getChildText(ConstXmlModeleElements.ELEMENT_X)),
                        Integer.parseInt(xmlTextElement.getChildText(ConstXmlModeleElements.ELEMENT_Y)),
                        Integer.parseInt(xmlTextElement.getChildText(ConstXmlModeleElements.ELEMENT_CARACTERESMAX)),
                        Integer.parseInt(xmlTextElement.getChildText(ConstXmlModeleElements.ELEMENT_TAILLEFONT)));

                List<Element> xmlImageElements = xmlModele.getChild(ConstXmlModeleElements.ELEMENT_IMAGES).getChildren();
                ZoneImage[] zoneImages = new ZoneImage[xmlImageElements.size()];
                int compteur = 0;
                for(Element xmlImageElement : xmlImageElements){
                    zoneImages[compteur] = new ZoneImage(
                            Integer.parseInt(xmlImageElement.getChildText(ConstXmlModeleElements.ELEMENT_X)),
                            Integer.parseInt(xmlImageElement.getChildText(ConstXmlModeleElements.ELEMENT_Y)),
                            Integer.parseInt(xmlImageElement.getChildText(ConstXmlModeleElements.ELEMENT_LONGEUR)),
                            Integer.parseInt(xmlImageElement.getChildText(ConstXmlModeleElements.ELEMENT_HAUTEUR)),
                            Integer.parseInt(xmlImageElement.getChildText(ConstXmlModeleElements.ELEMENT_ROTATION)));
                    ++compteur;
                }

                modeles.add(new ModeleCarte(orientation, zoneDeTexte, zoneImages));

                if( ++i >= NB_MODELE_MAX )
                        return modeles;
            }
        }

        return modeles;
    }
}
